﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SilverlightMediaFramework.Data;
using Microsoft.SilverlightMediaFramework.Data.Settings;
using Microsoft.SilverlightMediaFramework.Player;
using SMF.HowTo.Data;
using SMF.HowTo.Model;
using SMF.HowTo.Shared;
using SMF.HowTo.Shared.Eventing;
using SMF.HowTo.Shared.Extensions;
using SMF.HowTo.UI.ViewModels.Events;

namespace SMF.HowTo.UI.ViewModels
{
    public class PlayerViewModel : ViewModelBase
    {
        private const string VideoInfoDataSourceName = "VideoInfo";
        private readonly Action<CustomMarker> _selectMarkerAction;
        private readonly EasterEggUnlocker _easterEggUnlocker;
        private readonly int[] _easterEggKey = new int[] { 0, 1, 1, 2, 3, 5};

        private bool _isVisible = true;
        private IEnumerable<Marker> _markers;
        private MarkerDataClient _markersClient;
        private CustomMarker _selectedMarker;
        private VideoInfo _selectedVideo;
        private VideoInfoDataClient _videoInfoDataClient;
        private IEnumerable<VideoInfo> _videos;

        public PlayerViewModel()
        {
            _easterEggUnlocker = new EasterEggUnlocker(_easterEggKey);
            _easterEggUnlocker.Unlocked += ShowEasterEgg;
            _selectMarkerAction = i => SelectedMarker = i;
            EventAggregator.EventPublished += EventPublished;
        }

        public bool IsVisible
        {
            get { return _isVisible; }
            set
            {
                if (_isVisible != value)
                {
                    _isVisible = value;
                    OnPropertyChanged("IsVisible");
                }
            }
        }

        public IEnumerable<Marker> Markers
        {
            get { return _markers; }
            private set
            {
                if (_markers != value)
                {
                    _markers = value;
                    OnPropertyChanged("Markers");
                }
            }
        }

        public CustomMarker SelectedMarker
        {
            get { return _selectedMarker; }
            private set
            {
                if (_selectedMarker != value)
                {
                    _selectedMarker = value;
                    OnPropertyChanged("SelectedMarker");
                }
            }
        }

        public IEnumerable<VideoInfo> Videos
        {
            get { return _videos; }
            private set
            {
                if (_videos != value)
                {
                    _videos = value;
                    OnPropertyChanged("Videos");
                }
            }
        }

        public VideoInfo SelectedVideo
        {
            get { return _selectedVideo; }
            set
            {
                if (_selectedVideo != value)
                {
                    _selectedVideo = value;
                    OnPropertyChanged("SelectedVideo");
                }
            }
        }

        private void EventPublished(Event evt)
        {
            if (evt is SettingsLoadedEvent)
            {
                SettingsBase settings = ((SettingsLoadedEvent) evt).Argument;
                this.IsVisible = true;
                LoadSettings(settings);
            }

            if (evt is EasterEggHiddenEvent)
            {
                this.IsVisible = true;
            }
        }

        private void ShowEasterEgg()
        {
            var evt = new ShowEasterEggEvent(TimeSpan.Parse("00:00:03"));
            EventAggregator.PublishEvent(evt);
            this.IsVisible = false;
        }

        private void LoadSettings(SettingsBase settings)
        {
            Source videoInfoDataSource = settings.DataSources
                .Where(i => i.Name == VideoInfoDataSourceName)
                .FirstOrDefault();

            if (videoInfoDataSource != null)
            {
                _videoInfoDataClient = new VideoInfoDataClient(videoInfoDataSource.Url);
                _videoInfoDataClient.FetchCompleted += (s, e) => LoadVideoInfo(e.Result.ToList());
                _videoInfoDataClient.FetchFailed += (s, e) => NotifyUser(e.Result.Message);
                _videoInfoDataClient.Fetch();
            }
        }

        private void LoadVideoInfo(IList<VideoInfo> videoInfo)
        {
            if (Videos != null)
            {
                Videos.ForEach(i => i.Selected -= LoadVideo);
            }

            Videos = videoInfo;
            videoInfo.ForEach(i => i.Selected += LoadVideo);
        }

        private void LoadVideo(VideoInfo selectedVideo)
        {
            ClearMarkers();
            SelectedVideo = selectedVideo;

            int index = this.Videos.ToList().IndexOf(selectedVideo);
            _easterEggUnlocker.Enter(index);

            if (selectedVideo.MarkersSource != null)
            {
                _markersClient = new MarkerDataClient(selectedVideo.MarkersSource);
                _markersClient.FetchCompleted += (s, e) => LoadMarkers(e.Result.ToList());
                _markersClient.FetchFailed += (s, e) => NotifyUser(e.Result.Message);
                _markersClient.Fetch();
            }
        }

        private void LoadMarkers(IList<CustomMarker> markers)
        {
            ClearMarkers();
            markers.ForEach(i => i.Selected += _selectMarkerAction);
            Markers = markers.Select(i => i as Marker);
        }

        private void ClearMarkers()
        {
            if (Markers != null)
            {
                Markers
                    .Select(i => i as CustomMarker)
                    .ForEach(i => i.Selected -= _selectMarkerAction);
                Markers = new List<Marker>();
            }
        }
    }
}